﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.AddIn.Pipeline;
using System.Globalization;
using System.Diagnostics;
using Toolbox.Plugin.Interfaces;
using System.ComponentModel.Composition;
using System.IO;
using System.Reflection;

namespace Toolbox.Plugin.FileHandler
{
    [DefaultMember("Directory")]
    [PartNotDiscoverable]
    public class FileHandler : Plugin
    {
        public int BatchSize { get; protected set; }
        public DateTime CurrentDate { get; protected set; }
        public Uri Directory { get; set; }

        #region ISupportInitialize Members

        public override void EndInit()
        {
            base.EndInit();

            if (this.Directory is Uri && this.Directory.Fragment.Length > 0)
            {
                string[] list = this.Directory.Fragment.Substring(1).Split(';');

                foreach (string data in list)
                {
                    string[] kvp = data.Split('=');
                    this.SetProperty(kvp[0], Uri.UnescapeDataString(kvp[1]));
                }
            }
        }

        #endregion

        #region DatePartition Helpers

        public delegate DateTime GetFileDate<T>(T o);

        public static DateTime GetFileInfoDate(FileInfo o)
        {
            return o.LastWriteTime;
        }

        public static int CompareFileDates(FileInfo x, FileInfo y)
        {
            return DateTime.Compare(x.LastWriteTime, y.LastWriteTime);
        }

        public static int GetDatePartition<T>(ref T[] files, int preferedsize, GetFileDate<T> d, DateTime newerthan)
        {
            return GetDatePartition<T>(ref files, preferedsize, d, newerthan, DateTime.Now);
        }

        public static int GetDatePartition<T>(ref T[] files, int preferedsize, GetFileDate<T> d, DateTime newerthan, DateTime olderthan)
        {
            // Filter by date, extention
            files = Array.FindAll<T>(files, delegate(T f) { return d(f) > newerthan && d(f) < olderthan; });

            // Sort by date ASC
            Array.Sort<T>(files, delegate(T f1, T f2)
            {
                return DateTime.Compare(d(f1), d(f2));
            });

            // Partitioning ~preferedsize, keep files of same date/time together
            int size = 0;
            for (size = files.Length < preferedsize ? files.Length : preferedsize; size < files.Length; size++)
            {
                if (d(files[size - 1]) < d(files[size]))
                {
                    break;
                }
            }

            // Resizing
            Array.Resize<T>(ref files, size);

            // Return real partition size
            return size;
        }

        #endregion

        protected static bool IsFileLocked(FileInfo file)
        {
            FileStream stream = null;

            try
            {
                stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None);
            }
            catch (FileNotFoundException)
            {
                return false;
            }
            catch (IOException)
            {
                return true;
            }
            finally
            {
                if (stream != null)
                    stream.Close();
            }

            return false;
        }
    }
}
